/**
 * 
 */
package algorithmusspielerei;

import java.lang.reflect.Array;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import entities.Appointment;
import entities.Category;
import fachlogik.Administration;

/**
 * @author Veit & Alex
 *
 */
public class RangeDayListTest {

private Administration admin;


public RangeDayListTest() throws ParseException {
    SimpleDateFormat sdfD = new SimpleDateFormat("dd.MM.yyyy");
    SimpleDateFormat sdfH = new SimpleDateFormat("HH:mm");
    
    Date d1 = sdfD.parse("01.01.2000");
    Date d2 = sdfD.parse("07.01.2000");
    Category c1 = new Category();
    c1.setAnfangszeit(new Date(sdfH.parse("08:00").getTime() + 1000 * 60 * 60));
    c1.setEndzeit(new Date(sdfH.parse("17:00").getTime() + 1000 * 60 * 60));
    System.out.println(categoryAppErstellen(tageAuflisten(d1, d2), c1));
    
    admin = Administration.getInstance();
    ArrayList<Appointment> alleApps = new ArrayList<>();
    for (Appointment a : admin.getAllAppointments())
        alleApps.add(a);
    
    admin.appointmentsSortieren(alleApps);
    
    freieTermine(categoryAppErstellen(tageAuflisten(d1, d2), c1).get(0), alleApps);
}

/**
 * @param args
 * @throws ParseException 
 */
public static void main(String[] args) throws ParseException {
    RangeDayListTest rdlt = new RangeDayListTest();
}



/**
 * 
 * @param zeitfenster
 * @param besetzteApps
 * @return freieTermine (invertierte)
 */

public ArrayList<Appointment> freieTermine (Appointment zeitfenster, List<Appointment> besetzteApps) { 
    ArrayList<Appointment> relevanteTermine = relevanteTermine(zeitfenster, besetzteApps);
    
    admin.appointmentsSortieren(relevanteTermine);
    ArrayList<Appointment> freieTermine = new ArrayList<>();
    
    if(relevanteTermine.size()==0){
        freieTermine.add(zeitfenster);
        return freieTermine;
    }
    
    //falls es nur einen relevanten Termin gibt
    if (relevanteTermine.size()==1){
        Appointment a = new Appointment();
        Appointment b = new Appointment();
        
        //1. Fall:
        //der einzige relevante Termin überschneidet sich mit dem Anfang des Zeitfensters
        // Überprüfung, ob sein Anfang vor Anfang Zeitfenster liegt
        if (relevanteTermine.get(0).getBegin().getTime() < zeitfenster.getBegin().getTime()){
            a.setBegin(relevanteTermine.get(0).getEnd());
            a.setEnd(zeitfenster.getEnd());
            freieTermine.add(a);
        }
        
        //2. Fall
        //der einzige relevante Termin überschneidet sich mit dem Ende des Zeitfensters
        //Überprüfung, ob sein Ende nach Ende Zeifenster liegt
        if (relevanteTermine.get(0).getEnd().getTime() > zeitfenster.getEnd().getTime()){
            a.setBegin(zeitfenster.getBegin());
            a.setEnd(relevanteTermine.get(0).getBegin());
            freieTermine.add(a);
        }
        
        //3. Fall
        //Termin liegt irgendwo im Zeitfenster
        //d.h. ein freier Termin vom Anfang Zeitfenster bis Anfang relevanter Termin
        // 2. freier Termin vom Ende Termin bis Ende Zeitfenster
        a.setBegin(zeitfenster.getBegin());
        a.setEnd(relevanteTermine.get(0).getBegin());
        freieTermine.add(a);
        
        b.setBegin(relevanteTermine.get(0).getEnd());
        b.setEnd(zeitfenster.getEnd());
        freieTermine.add(b); 
    }
    
    //falls der erste relevante Termin nach Anfang des Zeitfensters beginnt
    //d.h. ein freier Termin zwischen Zeitfenster-Anfang und Anfang erster relevanter Termin
    if (relevanteTermine.get(0).getBegin().getTime() > zeitfenster.getBegin().getTime()){
        Appointment a = new Appointment();
        a.setBegin(zeitfenster.getBegin());
        a.setEnd(relevanteTermine.get(0).getBegin());
        freieTermine.add(a);
    }
    
    //falls der letzte relevante Termin vor Ende des Zeitfensters aufhört
    //d.h. ein freier Termin zwischen Ende letzter relevanter Termin und Ende Zeitfenster
    if (relevanteTermine.get(relevanteTermine.size()-1).getEnd().getTime() < zeitfenster.getEnd().getTime()){
        Appointment a = new Appointment();
        a.setBegin(relevanteTermine.get(relevanteTermine.size()-1).getEnd());
        a.setEnd(zeitfenster.getEnd());
    }
    
    for(int i = 0; i < relevanteTermine.size()-1; i++){
        if (relevanteTermine.get(i).getEnd()!=relevanteTermine.get(i+1).getBegin()) {
            Appointment a = new Appointment();
            a.setBegin(relevanteTermine.get(i).getEnd());
            a.setEnd(relevanteTermine.get(i+1).getBegin());
            freieTermine.add(a);
        }
    }
    
    admin.appointmentsSortieren(freieTermine);
    return freieTermine;
}

public ArrayList<Appointment> relevanteTermine (Appointment zeitfenster, List<Appointment> besetzteApps) {
    ArrayList<Appointment> relevanteTermine = new ArrayList<>();
    for (Appointment a : besetzteApps){
        if (datumInnerhalbApp(a.getBegin(), zeitfenster) || datumInnerhalbApp(a.getEnd(), zeitfenster)){
            relevanteTermine.add(a);
        }
    }
    return relevanteTermine;
}



/**
 * Gibt true wenn Datum innerhalb eines Termins ist.
 * @param a
 * @param d
 * @return
 */
public boolean datumInnerhalbApp (Date d, Appointment a) {
    if(a.getBegin().getTime() <= d.getTime() && a.getEnd().getTime() >= d.getTime())
        return true;
    return false;
}

public ArrayList<Appointment> categoryAppErstellen (ArrayList<Date> dates, Category c){
    ArrayList<Appointment> apps = new ArrayList<>();
    
    for (Date d: dates){
        Appointment a = new Appointment();
        Date anfang = new Date(0);
        Date ende = new Date(0);
        anfang.setTime(c.getAnfangszeit().getTime()+d.getTime());
        ende.setTime(c.getEndzeit().getTime() + d.getTime());
        a.setBegin(anfang);
        a.setEnd(ende);
        apps.add(a);
    }
    return apps;
}


public ArrayList<Date> tageAuflisten (Date d1, Date d2) {
    ArrayList<Date> dates = new ArrayList<>();
    long tag = 24 * 60 * 60 * 1000;
    while (d1.getTime() <= d2.getTime()){
        Date d = new Date();
        d.setTime(d1.getTime());
        dates.add(d);
        d1.setTime(d1.getTime()+tag);
    }
    return dates;
}


}
